#include "qeditorfactory.h"

#include "../../include/abstractcore.h"
#include "../../lib/shared/qproject.h"
#include "../../include/qcommonstruct.h"

#include "qscripteditdialog.h"
#include "qproperty.h"
#include "qchosseimage.h"
#include "qeditcomboboxitems.h"
#include "qmemeryvaluesetdialog.h"
#include "qsetpaddingdialog.h"
#include "qsetborderdialog.h"

#include <QFontDatabase>
#include <QHBoxLayout>
#include <QFontDialog>
#include <QMetaProperty>
#include <QMetaEnum>
#include <QCursor>
#include <QColorDialog>

static  QFontDatabase   fontDataBase;


QSpinBoxEditor::QSpinBoxEditor(QProperty *property, QWidget *parent):
    QSpinBox(parent),
    m_property(property)
{
    this->setFrame(false);
    this->setRange(property->attribute("min",0x80000000).toInt(),property->attribute("max",0x7f000000).toInt());
    setValue(property->value().toInt());
    connect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
}

void QSpinBoxEditor::setPropertyValue()
{
    int v=this->value();
    if(v!=m_property->value().toInt())
    {
        m_property->setModified(true);
        m_property->setValue(this->value());
    }
}

void QSpinBoxEditor::propertyValueChanged()
{
    this->setValue(m_property->value().toInt());
}


QDoubleSpinBoxEditor::QDoubleSpinBoxEditor(QProperty *property, QWidget *parent):
    QDoubleSpinBox(parent),
    m_property(property)
{
    this->setFrame(false);
    this->setRange(property->attribute("min","-999999999").toDouble(),property->attribute("max","999999999").toDouble());
    this->setDecimals(property->attribute("decimals",2).toInt());
    setValue(property->value().toDouble());
    connect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
}

void QDoubleSpinBoxEditor::setPropertyValue()
{
    double d=this->value();
    if(d!=m_property->value().toDouble())
    {
        m_property->setModified(true);
        m_property->setValue(this->value());
    }
}

void QDoubleSpinBoxEditor::propertyValueChanged()
{
    this->setValue(m_property->value().toDouble());
}


QLabelEditor::QLabelEditor(QProperty *property, QWidget *parent):
    QWidget(parent),
    m_property(property),
    m_icon(new QLabel(this)),
    m_text(new QLabel(this))
{
    m_text->setText(property->valueText());
    QIcon icon=m_property->valueIcon();
    if(icon.isNull())
    {
        m_icon->setVisible(false);
    }
    else
    {
        QPixmap pix=icon.pixmap(QSize(16,16));
        m_icon->setFixedSize(16,16);
        m_icon->setPixmap(pix);
    }

    QHBoxLayout *l=new QHBoxLayout;
    this->setLayout(l);
    l->setMargin(0);
    l->setSpacing(0);
    l->addWidget(m_icon);
    l->addWidget(m_text);

    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
}

void QLabelEditor::propertyValueChanged()
{
    m_text->setText(m_property->valueText());
    QIcon icon=m_property->valueIcon();
    if(icon.isNull())
    {
        m_icon->setVisible(false);
    }
    else
    {
        QPixmap pix=icon.pixmap(QSize(16,16));
        m_icon->setFixedSize(16,16);
        m_icon->setPixmap(pix);
        m_icon->setVisible(true);
    }
}

QByteEditor::QByteEditor(QProperty *property, QWidget *parent):
    QLineEdit(parent),
    m_property(property)
{
    setText(property->valueText());
    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
    connect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
    this->setFrame(false);
}

void QByteEditor::propertyValueChanged()
{
    disconnect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
    this->setText(m_property->valueText());
    connect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
}

void QByteEditor::setPropertyValue()
{
    if(this->text()!=m_property->value().toString())
    {
        m_property->setModified(true);
        m_property->setValue(this->text());
    }

}

QNameLineEditor::QNameLineEditor(QProperty *property, QWidget *parent):
    QNameEdit(parent),
    m_property(property)
{
    setValue(property->valueText());
    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
    connect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
    this->setFrame(false);

    QObject *obj=property->object()->parent();

    QStringList list;
    QObjectList objlist=obj->children();

    foreach(QObject *o,objlist)
    {
        if(o==property->object() || !o->property("designer_widget").toBool())
        {
            continue;
        }
        else
        {
            list.append(o->property("objectName").toString());
        }
    }

    QProject *p=QProject::project();
    int c=p->getPageCount();
    for(int i=0;i<c;i++)
    {
        list.append(p->getPage(i).m_name);
    }

    this->setIntermediateList(list);

}

void QNameLineEditor::propertyValueChanged()
{
    disconnect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
    this->setValue(m_property->valueText());
    connect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
}

void QNameLineEditor::setPropertyValue()
{
    if(value()!=m_property->value().toString())
    {
        m_property->setModified(true);
        m_property->setValue(value());
    }
}


QBoolEditor::QBoolEditor(QProperty *property, QWidget *parent):
    QCheckBox(parent),
    m_property(property)
{
    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
    setChecked(m_property->value().toBool());
    this->setFixedHeight(15);
}

void QBoolEditor::setPropertyValue()
{
    m_property->setModified(true);
    m_property->setValue(this->isChecked());

}

void QBoolEditor::propertyValueChanged()
{
    setChecked(m_property->value().toBool());
}

void QBoolEditor::mousePressEvent(QMouseEvent *e)
{
    this->setChecked(!this->isChecked());
    setPropertyValue();
}

QFontFamilyEditor::QFontFamilyEditor(QProperty *property, QWidget *parent):
    QComboBox(parent),
    m_property(property)
{
    QStringList list=fontDataBase.families();

    this->addItems(list);

    int index=list.indexOf(property->value().toString());
    if(index<0)
    {
        index=0;
    }
    this->setCurrentIndex(index);

    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
    connect(this,SIGNAL(currentIndexChanged(QString)),this,SLOT(setPropertyValue(QString)));
}

void QFontFamilyEditor::propertyValueChanged()
{
    disconnect(this,SIGNAL(currentIndexChanged(QString)),this,SLOT(setPropertyValue(QString)));

    int index=this->findText(m_property->value().toString());
    if(index<0)
    {
        index=0;
    }
    this->setCurrentIndex(index);

    connect(this,SIGNAL(currentIndexChanged(QString)),this,SLOT(setPropertyValue(QString)));
}

void QFontFamilyEditor::setPropertyValue(QString family)
{
    m_property->setModified(true);
    m_property->setValue(family);

}


QFontEditor::QFontEditor(QProperty *property, QWidget *parent):
    QLabelEditor(property,parent),
    m_property(property),
    m_button(new QToolButton(this))
{
    QLayout *l=this->layout();
    l->addWidget(m_button);
    m_button->setText("...");
    m_button->setFixedWidth(25);
    connect(m_button,SIGNAL(clicked()),this,SLOT(showFontDialog()));
}

void QFontEditor::showFontDialog()
{
    bool ok;
    QFont font = QFontDialog::getFont(&ok,m_property->value().value<QFont>(), this);
    if (ok)
    {
        m_property->setModified(true);
        m_property->setValue(QVariant(font));

    }
}


QEnumEditor::QEnumEditor(QProperty *property, QWidget *parent):
    QComboBox(parent),
    m_property(property)
{
    QObject *o=m_property->object();
    QMetaEnum e=o->metaObject()->property(o->metaObject()->indexOfProperty(property->name().toLocal8Bit())).enumerator();
    if(e.isValid())
    {
        for(int i=0;i<e.keyCount();i++)
        {
            this->addItem(e.valueToKey(e.value(i)));
        }
    }

    int index=this->findText(e.valueToKey(m_property->value().toInt()));
    if(index<=0)
    {
        index=0;
    }
    setCurrentIndex(index);


    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
    connect(this,SIGNAL(currentIndexChanged(int)),this,SLOT(setPropertyValue(int)));
}

void QEnumEditor::propertyValueChanged()
{
    disconnect(this,SIGNAL(currentIndexChanged(int)),this,SLOT(setPropertyValue(int)));

    QObject *o=m_property->object();
    QMetaEnum e=o->metaObject()->property(o->metaObject()->indexOfProperty(m_property->name().toLocal8Bit())).enumerator();
    int index=this->findText(e.valueToKey(m_property->value().toInt()));
    if(index<=0)
    {
        index=0;
    }
    setCurrentIndex(index);

   connect(this,SIGNAL(currentIndexChanged(int)),this,SLOT(setPropertyValue(int)));
}

void QEnumEditor::setPropertyValue(int value)
{
    QObject *o=m_property->object();
    QMetaEnum e=o->metaObject()->property(o->metaObject()->indexOfProperty(m_property->name().toLocal8Bit())).enumerator();

    m_property->setModified(true);
    m_property->setValue(e.value(value));

}


QCursorEditor::QCursorEditor(QProperty *property, QWidget *parent):
    QComboBox(parent),
    m_property(property)
{
    QCursorProperty *p=(QCursorProperty*)property;

    QStringList text=p->textList();
    QStringList icon=p->iconList();

    for(int i=0;i<text.size();i++)
    {
        addItem(QIcon(icon.at(i)),text.at(i));
    }

    setCurrentIndex(m_property->value().value<QCursor>().shape());


    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
    connect(this,SIGNAL(currentIndexChanged(int)),this,SLOT(setPropertyValue(int)));
}

void QCursorEditor::propertyValueChanged()
{
    disconnect(this,SIGNAL(currentIndexChanged(int)),this,SLOT(setPropertyValue(int)));

    setCurrentIndex(m_property->value().value<QCursor>().shape());

   connect(this,SIGNAL(currentIndexChanged(int)),this,SLOT(setPropertyValue(int)));
}

void QCursorEditor::setPropertyValue(int value)
{
    m_property->setModified(true);
    m_property->setValue(QCursor((Qt::CursorShape)value));

}

QComboItemEditor::QComboItemEditor(QProperty *property, QWidget *parent):
    QLabelEditor(property,parent),
    m_property(property),
    m_button(new QToolButton(this))
{
    QLayout *l=this->layout();
    l->addWidget(m_button);
    m_button->setText("...");
    m_button->setFixedWidth(25);

    connect(m_button,SIGNAL(clicked()),this,SLOT(showFontDialog()));
}

void QComboItemEditor::showFontDialog()
{
    QEditComboBoxItems dlg(this);

    dlg.setValue(m_property->value());
    if(dlg.exec())
    {
        QVariant v=dlg.value();
        if(v!=m_property->value())
        {
            m_property->setModified(true);
            m_property->setValue(v);

        }
    }
}


QTimeEditor::QTimeEditor(QProperty *property, QWidget *parent):
    QTimeEdit(parent),
    m_property(property)
{
    this->setTime(m_property->value().toTime());
    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
    connect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
}

void QTimeEditor::propertyValueChanged()
{
    this->setTime(m_property->value().toTime());
}

void QTimeEditor::setPropertyValue()
{
    QTime dt=this->time();
    if(dt!=m_property->value().toTime())
    {
        m_property->setModified(true);
        m_property->setValue(this->time());
    }
}



QDateEditor::QDateEditor(QProperty *property, QWidget *parent):
    QDateEdit(parent),
    m_property(property)
{
    this->setDate(m_property->value().toDate());
    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
    connect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
}

void QDateEditor::propertyValueChanged()
{
    this->setDate(m_property->value().toDate());
}

void QDateEditor::setPropertyValue()
{
    QDate dt=this->date();
    if(dt!=m_property->value().toDate())
    {
        m_property->setModified(true);
        m_property->setValue(this->date());
    }
}


QDateTimeEditor::QDateTimeEditor(QProperty *property, QWidget *parent):
    QDateTimeEdit(parent),
    m_property(property)
{
    this->setDateTime(m_property->value().toDateTime());
    connect(m_property,SIGNAL(changed()),this,SLOT(propertyValueChanged()));
    connect(this,SIGNAL(editingFinished()),this,SLOT(setPropertyValue()));
}

void QDateTimeEditor::propertyValueChanged()
{
    this->setDateTime(m_property->value().toDateTime());
}

void QDateTimeEditor::setPropertyValue()
{
    QDateTime dt=this->dateTime();
    if(dt!=m_property->value().toDateTime())
    {
        m_property->setModified(true);
        m_property->setValue(this->dateTime());
    }

}

QColorEditor::QColorEditor(QProperty *property, QWidget *parent):
    QLabelEditor(property,parent),
    m_property(property),
    m_button(new QToolButton(this))
{
    QLayout *l=this->layout();
    l->addWidget(m_button);
    m_button->setText("...");
    m_button->setFixedWidth(25);

    connect(m_button,SIGNAL(clicked()),this,SLOT(showColorDialog()));
}

void QColorEditor::showColorDialog()
{
    tagColorInfo info=m_property->value().value<tagColorInfo>();
    QColor c=QColorDialog::getColor(info.m_type==0?QColor(255,255,255):info.m_color,this,"",QColorDialog::ShowAlphaChannel);
    if(c.isValid())
    {
        if(c!=info.m_color)
        {
            m_property->setModified(true);
            QVariant v;
            info.m_type=1;
            info.m_color=c;
            v.setValue(info);
            m_property->setValue(v);
        }
    }
}

QBorderEditor::QBorderEditor(QProperty *property, QWidget *parent):
    QLabelEditor(property,parent),
    m_property(property),
    m_button(new QToolButton(this))
{
    QLayout *l=this->layout();
    l->addWidget(m_button);
    m_button->setText("...");
    m_button->setFixedWidth(25);

    connect(m_button,SIGNAL(clicked()),this,SLOT(showBorderDialog()));
}

void QBorderEditor::showBorderDialog()
{
    tagBorderInfo info=m_property->value().value<tagBorderInfo>();
    QSetBorderDialog dlg(this);
    dlg.setBorderInfo(info);
    dlg.exec();
    if(dlg.getRet()==1)
    {
        tagBorderInfo ret=dlg.getBorderInfo();
        if(!(ret==info))
        {
            m_property->setModified(true);
            QVariant v;
            v.setValue(ret);
            m_property->setValue(v);
        }
    }
}

QImageEditor::QImageEditor(QProperty *property, QWidget *parent):
    QLabelEditor(property,parent),
    m_property(property),
    m_button(new QToolButton(this))
{
    QLayout *l=this->layout();
    l->addWidget(m_button);
    m_button->setText("...");
    m_button->setFixedWidth(25);

    connect(m_button,SIGNAL(clicked()),this,SLOT(showImageDialog()));
}

void QImageEditor::showImageDialog()
{
    QChosseImage dlg(m_property->core(),this);


    tagImageInfo info=m_property->value().value<tagImageInfo>();

    dlg.init(info.m_name,QRect(info.m_left,info.m_top,info.m_right,info.m_bottom),info.m_type);
    dlg.setEnabledList(m_property->attribute("enabledList").toStringList());
    if(dlg.exec()==1)
    {
        tagImageInfo in;
        in.m_name=dlg.getResource();
        in.m_type=dlg.getType();
        QRect re=dlg.getBorder();
        in.m_left=re.left();
        in.m_top=re.top();
        in.m_right=re.width();
        in.m_bottom=re.height();
        QVariant v;
        v.setValue<tagImageInfo>(in);
        if(!(in==info))
        {
            if(info.m_name!=in.m_name)
            {
                QProject::project()->insertResource(in.m_name,m_property->object(),m_property->name());
            }
            m_property->setModified(true);
            m_property->setValue(v);
        }
    }
}


QMemeryValueEditor::QMemeryValueEditor(QProperty *property, QWidget *parent):
    QLabelEditor(property,parent),
    m_property(property),
    m_button(new QToolButton(this))
{
    QLayout *l=this->layout();
    l->addWidget(m_button);
    m_button->setText("...");
    m_button->setFixedWidth(25);

    connect(m_button,SIGNAL(clicked()),this,SLOT(showMemeryValueDialog()));
}

void QMemeryValueEditor::showMemeryValueDialog()
{
    QMemeryValueSetDialog dlg(m_property->object(),this);
    dlg.setValue(m_property->value());
    if(dlg.exec()==1)
    {
        QVariant v=dlg.value();
        bool c=false;
        MemeryValueItems old=m_property->value().value<MemeryValueItems>();
        MemeryValueItems now=v.value<MemeryValueItems>();
        if(old.size()!=now.size())
        {
            c=true;
        }
        else
        {
            for(int i=0;i<old.size();i++)
            {
                tagMemeryValueInfo o=old.at(i);
                tagMemeryValueInfo n=now.at(i);
                if(!(o==n))
                {
                    c=true;
                    break;
                }
            }
        }
        if(c)
        {
            m_property->setModified(true);
            m_property->setValue(v);
        }
    }
}

QScriptEditor::QScriptEditor(QProperty *property, QWidget *parent):
    QLabelEditor(property,parent),
    m_property(property),
    m_button(new QToolButton(this))
{
    QLayout *l=this->layout();
    l->addWidget(m_button);
    m_button->setText("...");
    m_button->setFixedWidth(25);

    connect(m_button,SIGNAL(clicked()),this,SLOT(showScriptEditDialog()));
}

void QScriptEditor::showScriptEditDialog()
{
    m_edit=new QScriptEditDialog(m_property,this);
    connect(m_edit,SIGNAL(save(QString)),this,SLOT(scripteChanged(QString)));
    m_edit->exec();

    delete m_edit;
}

void QScriptEditor::scripteChanged(const QString &script)
{
    QString str=m_property->value().toString();
    if(str!=script)
    {
        m_property->setModified(true);
        m_property->setValue(script);
    }
}


QPaddingEditor::QPaddingEditor(QProperty *property, QWidget *parent):
    QLabelEditor(property,parent),
    m_property(property),
    m_button(new QToolButton(this))
{
    QLayout *l=this->layout();
    l->addWidget(m_button);
    m_button->setText("...");
    m_button->setFixedWidth(25);

    connect(m_button,SIGNAL(clicked()),this,SLOT(showPaddingEditDialog()));
}

void QPaddingEditor::showPaddingEditDialog()
{
    QSetPaddingDialog dlg(this);
    dlg.setValue(m_property->value().value<tagPaddingInfo>());
    if(dlg.exec())
    {
        tagPaddingInfo padding=dlg.value();
        if(!(padding==m_property->value().value<tagPaddingInfo>()))
        {
            m_property->setModified(true);
            QVariant v;
            v.setValue<tagPaddingInfo>(padding);
            m_property->setValue(v);
        }
    }
}
